package com.nexus.plugin.security;

import com.nexus.plugin.security.exception.CustomAccessDeniedHandler;
import com.nexus.plugin.security.exception.CustomAuthenticationEntryPoint;
import com.nexus.plugin.security.exception.CustomAuthenticationFailureHandler;
import com.nexus.plugin.security.filter.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Security配置
 * @Date 2025/7/31 13:48
 * @Author luzhengning
 **/
@Configuration
@EnableWebSecurity
//@EnableWebFluxSecurity
public class SecurityConfig {

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    /**
     * 未认证异常
     *
     * @Date 2025/7/31 17:36
     * @Author luzhengning
     **/
    @Autowired
    private CustomAuthenticationEntryPoint authenticationEntryPoint;
    /**
     * 权限不足处理
     *
     * @Date 2025/7/31 17:52
     * @Author luzhengning
     **/
    @Autowired
    private CustomAccessDeniedHandler accessDeniedHandler;
    /**
     * 登录失败处理
     *
     * @Date 2025/7/31 17:52
     * @Author luzhengning
     **/
    @Autowired
    private CustomAuthenticationFailureHandler authenticationFailureHandler;

    /**
     * 配置安全过滤链
     *
     * @Date 2025/7/31 13:52
     * @Author luzhengning
     **/
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 关闭csrf
        http.csrf(AbstractHttpConfigurer::disable);
        // 配置URL访问权限
        Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer = new Customizer<AuthorizeHttpRequestsConfigurer<org.springframework.security.config.annotation.web.builders.HttpSecurity>.AuthorizationManagerRequestMatcherRegistry>() {
            @Override
            public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry authorize) {
                // 放行系统登录接口
                authorize.requestMatchers("/auth/sys/login").permitAll();
                authorize.requestMatchers("/auth/test1","/sys/test2","/druid/**").permitAll();
                // 所有接口都需要认证
                authorize.anyRequest().authenticated();
            }
        };
        http.authorizeHttpRequests(authorizeHttpRequestsCustomizer);
        // 配置表单登录
        http.formLogin(form -> form.loginPage("/login") // 自定义登录页
                .failureHandler(authenticationFailureHandler)// 登录失败处理
                .permitAll());
        // 配置会话管理为无状态
        http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        // 配置异常处理
        http.exceptionHandling(exception -> exception.authenticationEntryPoint(authenticationEntryPoint)  // 未认证访问处理
                .accessDeniedHandler(accessDeniedHandler)          // 权限不足处理
        );
        // 配置注销
        http.logout(logout -> logout.logoutSuccessUrl("/login?logout").permitAll());
        // Token过滤器
        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }


    /**
     * 配置密码编码器
     *
     * @Date 2025/7/31 13:52
     * @Author luzhengning
     **/
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 自定义登录接口需要调用AuthenticationManager.authenticate进行Security登录流程。
     *
     * @Date 2025/7/31 14:27
     * @Author luzhengning
     **/
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }


}
